﻿//=======================================================
// 作者：LR
// 公司：广州纷享科技发展有限公司
// 描述：
// 创建时间：2019-12-11 18:14:56
//=======================================================
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;

#if UNITY_EDITOR
using UnityEditor;
#endif

public class AnimatorEditorInspector : EditorSceneGUICustom<AnimatorEditorInspector,Animator>
{
    [InitializeOnLoadMethod]
    static void NewInitGUI()
    {
        GameObjectOverrideInspector.GUIHander.Add(OnCustomGUI);
    }


    public override void Show(GameObject go)
    {
        Init(go.GetComponent<Animator>());
    }

    public override void Hide()
    {
        AnimatorSceneViewEditor.Hide();
        StopEvent();
    }





    public struct ToolData
    {
        public int animatorCount;
        public int particleCount;
        public Animator mainAnimator;
    }


    const int frames = 60;

    ToolData data;

    ParticleEditor[] m_ParticleEtrs;
    AnimatorEditor[] m_Animators;

   



    public void Init(Animator animator)
    {
        if (Application.isPlaying)
            return;

        if (animator.gameObject.activeInHierarchy == false)
            return;

        if (animator.runtimeAnimatorController == null)
            return;

        if(animator.runtimeAnimatorController.animationClips.Length == 0)
           return;


        FindAllComponets();

        data = new ToolData { animatorCount = m_Animators.Length, particleCount = m_ParticleEtrs.Length, mainAnimator = animator };

        AnimatorSceneViewEditor.Init(data);

        AnimatorSceneViewEditor.editorState.stateEvent += (id) =>
        {
            if (id == 0)
            {
                PlayEvent();
            }
            if (id == 2)
            {
                StopEvent();
            }
        };

        AnimatorSceneViewEditor.editorMovie.updateEvent += (time, radio, delta, allTime) =>
        {
            try
            {
                if (radio == 0)
                {
                    PreviewParticleReset();
                    PreviewAnimatorReset();
                }

                PreviewAnimatorShow(time, delta, allTime);
                PreviewParticleShowLength(time);
            }
            catch { }
        };
    }

    public void PlayEvent()
    {
        foreach (var item in m_Animators)
        {
            item.Rewind();
        }
    }

    public void StopEvent()
    {
        PreviewAnimatorReset();
        PreviewParticleStop();
    }



    #region 预览各种组件


    /// <summary>
    /// 预览特效组件
    /// </summary>
    private void PreviewParticleReset()
    {
        foreach (var item in m_ParticleEtrs)
        {
            item.Reset();
        }
    }


    public void PreviewParticleStop()
    {
        if (m_ParticleEtrs != null)
        {
            foreach (var item in m_ParticleEtrs)
            {
                item.Stop();
            }
        }
    }

    /// <summary>
    /// 预览特效组件
    /// </summary>
    private void PreviewParticleShowLength(float allTime)
    {
        foreach (var item in m_ParticleEtrs)
        {
            item.SimulateLength(allTime);
        }
    }


    /// <summary>
    /// 预览新的动画组件
    /// </summary>
    private void PreviewAnimatorShow(float time, float deltaTime, float allTime)
    {
        if (m_Animators != null)
        {
            foreach (var item in m_Animators)
            {
                item.Play(time, deltaTime, allTime, (int)(allTime * frames + 1), frames);
            }
        }
    }

    private void PreviewAnimatorReset()
    {
        if (m_Animators != null)
        {
            foreach (var item in m_Animators)
            {
                item.Reset();
            }
        }
    }


    #endregion

    /// <summary>
    /// 查找所有需要的组件
    /// </summary>
    private void FindAllComponets()
    {
        if (Selection.activeTransform)
        {
            Animator[]       t_Animators = Selection.activeTransform.GetComponentsInChildren<Animator>(true);
            ParticleSystem[] t_Particles = Selection.activeTransform.GetComponentsInChildren<ParticleSystem>(true);

            m_ParticleEtrs = t_Particles.Select(_ => new ParticleEditor() { particle = _ }).ToArray();
            m_Animators    = t_Animators.Select(_ => new AnimatorEditor() { atr      = _ }).ToArray();
        }
    }
}

public class ParticleEditor
    {
        public float lostTime;
        public ParticleSystem particle;
        bool isPlay = false;


        public void Reset()
        {
            isPlay = false;
            particle.time = 0.0f;
            particle.Play();
        }


        public void Stop()
        {
            isPlay = false;
            if (particle != null)
            {
                particle.time = 0;
                particle.Simulate(0);
                particle.Stop();
                particle.useAutoRandomSeed = false;
            }
        }



        public void Simulate(float deltaTime)
        {
            if (particle.gameObject.activeInHierarchy == false)
            {
                isPlay = false;
            }


            if (particle.gameObject.activeInHierarchy && isPlay == false)
            {
                isPlay = true;
                particle.time = 0;
                particle.Play();
                particle.Simulate(0.005f);
                particle.useAutoRandomSeed = false;
            }

            if (isPlay)
            {     
                particle.Simulate(deltaTime, false, false);
            }
        }


        public void SimulateLength(float curTime)
        {
            if (particle.gameObject.activeInHierarchy == false)
            {
                lostTime = curTime;
            }

            if (particle.gameObject.activeInHierarchy)
            {
                isPlay = true;
                particle.Simulate(curTime - lostTime);
            }
        }
    }

    public class AnimatorEditor
    {
        float lostTime;
        public Animator atr;

        public void Record(float frames, int frameCount)
        {
            atr.Rebind();
            atr.StopPlayback();
            atr.recorderStartTime = 0f;
            atr.StartRecording(frameCount);//录制frameCount时长的动作

            for (int i = 1; i <= frameCount; i++)
            {
                //记录每一帧的数据
                atr.Update(1.0f / frames);
            }
            //停止录制
            atr.StopRecording();

            //准备播放动作
            atr.StartPlayback();
            atr.playbackTime = 0f;
            atr.Update(0);
        }


        public void Rewind()
        {
            atr.Rebind();
        }


        public void Reset()
        {
            atr.playbackTime = 0;
            atr.Update(0);
            atr.StopPlayback();
        }



        public void Stop()
        {
            if (atr.gameObject.activeInHierarchy)
            {
                atr.playbackTime = 0;
                atr.Update(0);

                atr.StopPlayback();
                atr.StopRecording();
            }
            atr = null;
            System.GC.Collect();        
        }


        public void Play(float runTime, float deltaTime, float framesTime,int frameCount,int frames=60)
        {
            if (atr.gameObject.activeInHierarchy == false)
            {
                lostTime = runTime;
                return;
            }

            if (atr.recorderMode == AnimatorRecorderMode.Offline && atr.gameObject.activeInHierarchy)
            {
                Record(frames, frameCount);
                atr.StartPlayback();
            }

            atr.playbackTime = Mathf.Clamp(runTime - lostTime, 0.0f, framesTime - 0.1f);
            atr.Update(deltaTime);
        }
    }

